//
// Created by devink on 8/24/17.
//

#include "channel.h"
#include <sys/poll.h>
#include <unistd.h>
#include "eventloop.h"
#include "util/log.h"

using namespace dong;

const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = POLLIN | POLLPRI;
const int Channel::kWriteEvent = POLLOUT;

Channel::Channel(Eventloop *loop, int fd):loop_(loop),fd_(fd){
    loop_->addChannel(this);
}

Channel::~Channel() {
    close();
}

void Channel::close() {
    if (fd_>=0) {
        loop_->removeChannel(this);
        ::close(fd_);
        fd_ = -1;
    }
}

void Channel::enableRead(bool enable) {
    if (enable) {
        events_ |= kReadEvent;
    } else {
        events_ &= ~kReadEvent;
    }
    updateInPoller();
}

void Channel::enableWrite(bool enable) {
    if (enable) {
        events_ |= kWriteEvent;
    } else {
        events_ &= ~kWriteEvent;
    }
    updateInPoller();
}

void Channel::enableReadWrite(bool readable, bool writable) {
    if (readable) {
        events_ |= kReadEvent;
    } else {
        events_ &= ~kReadEvent;
    }
    if (writable) {
        events_ |= kWriteEvent;
    } else {
        events_ &= ~kWriteEvent;
    }
    updateInPoller();
}

bool Channel::readEnabled() {
    return events_ & kReadEvent;;
}

bool Channel::writeEnabled() {
    return events_ & kWriteEvent;;
}

void Channel::updateInPoller() {
    loop_->updateInPoller(this);
}

void Channel::handleEvent(int pollRetMs) {

    eventHandling_ = true;
    if (revents_ & (POLLERR | POLLNVAL))
    {
        if (errorcb_) errorcb_();
    }
    if (revents_ & (POLLIN | POLLPRI | POLLRDHUP))
    {
        if (readcb_) readcb_();
    }
    if (revents_ & POLLOUT)
    {
        if (writecb_) writecb_();
    }
    eventHandling_ = false;
}

void Channel::remove() {

    loop_->removeChannel(this);
}
